3Dmol.js¶

David Koes¶

3/14/2024¶

VIZBI¶

In [34]:
%%html
<script src="https://bits.csb.pitt.edu/preamble.js"></script>
In [35]:
%%html
<style>
.slides .viewerbackground {
    position: fixed; 
    left: 0; 
    top:  0; 
    min-height: 100%;
    width: 100%;
    pointer-events: auto;
    z-index: -1;
}
 .reveal .slides>section>section:has(.viewerbackground) {
    pointer-events: none; 
}
        
.slides .jp-InputPrompt {
    display: none;
}        

.slides .jp-OutputPrompt,.jp-OutputArea-prompt {
    display: none;
}
        
.reveal .slides .jp-RenderedHTMLCommon .highlight {
    background: none;
}
        
.slides .jp-RenderedHTMLCommon pre, .slides .jp-RenderedHTMLCommon code {
    background-color: rgba(255,255,255,0.7);
}        

.urlfloat {
    position: fixed;
    left: 50%;
    top: 5px;
    font-size:1.2em;
    color: #fff;
    transform: translate(-50%, 0);
    border-radius: 25px;
    background: #006;
    padding: 2px 10px 2px 10px; 
    z-index: 100;
    pointer-events: none;
    margin: auto;
    font-family: monospace;
}
</style>
<div style="height: 400px; width: 100%; z-index: -1;" class='viewerbackground' id='titlepage' ></div>       

<script>
$3Dmolpromise.then(function() {
var titleviewer = $3Dmol.createViewer('titlepage');
$3Dmol.download("pdb:1TUP",titleviewer).then(function(model) {
    let viewer = titleviewer;
 viewer.setViewStyle({style:"outline",color:"black", width:0.1});
 viewer.setStyle({}, {cartoon:{ribbon:true}});
 viewer.setStyle({chain:'A'}, {cartoon:{arrows:true, color:'spectrum', opacity:0.9}});
 viewer.setStyle({chain:'B'}, {cartoon:{style:"trace", color:'red'}});
 viewer.setStyle({chain:'C'}, {cartoon:{tubes:true, color:'purple'}});
 viewer.addSurface({},{opacity:0.85, color:'red'},{chain:'B'});
 viewer.addSurface({}, {opacity:0.8, color:'blue'},{chain:'C'});
 viewer.zoomTo();
 viewer.rotate(90,'x');
 viewer.rotate(-90,'y');
 viewer.render();
});
});

$('.reveal .slides>section>section:has(.viewerbackground)').on('touchstart', function(e){
  e.preventDefault();
});

$('body').append('<div class="urlfloat" >http://3dmol.org/talk</div>');
$(".jp-InputArea .o:contains(html)").closest('.jp-InputArea').hide();
</script>

What is 3Dmol.js?¶

A WebGL accelerated JavaScript library for interactive molecular graphics.

  • Can be embedded in web applications (including Jupyter notebooks)
  • Uses GPU to accelerate rendering
  • Real time interactivity

First Release: 2015¶

A product of necessity¶

Existing alternatives (in 2015) didn't cut it.

  • JMol: requires Java
  • JSMol: JMol transpiled to JavaScript - slooow
  • GLMol: Hobby project of Takanori Nakane. Used WebGL and Three.js, but slooooow

2016: Adoption of WebGL 2.0¶

Continuous Development¶

  • 47 contributors
  • multiple Google Summer of Code projects
  • features largely implemented in response to user issues

Current State of the Art¶

Much better than 2015.

3Dmol.js: Makes the simple things simple.

Usage: JavaScript API¶

<div style="height: 400px; width: 400px;" id="jsapi" ></div>
var viewer = $3Dmol.createViewer('jsapi');
viewer.addModel(data);
viewer.addStyle("line");
viewer.addSurface($3Dmol.SurfaceType.VDW, 
                  { opacity: 0.8, colorscheme: 'whiteCarbon' }, 
                  { chain: "A" }, { chain: "A" });
viewer.addStyle({ chain: "B" }, 
                { stick: { colorscheme: 'Jmol' } });
viewer.zoomTo({ chain: "B" });
viewer.render();









In [36]:
%%html
<div style="height: 400px; width: 100%; z-index: -1;" class='viewerbackground' id='jsapi' ></div>       

<script>

$3Dmolpromise.then(function() {
    var viewer = $3Dmol.createViewer('jsapi');

$3Dmol.download('pdb:1ycr',viewer,{}, function() {
  viewer.addStyle("line");
  viewer.addSurface('VDW', { opacity: 0.8, colorscheme: 'whiteCarbon' }, { chain: "A" }, { chain: "A" });
  viewer.addStyle({ chain: "B" }, { stick: { colorscheme: 'Jmol' } });
  viewer.zoomTo({ chain: "B" });
  viewer.render();
});
});
$(".jp-InputArea .o:contains(html)").closest('.jp-InputArea').hide();
</script>

Usage: Embedding API¶

<script src="https://3Dmol.org/build/3Dmol-min.js"></script>     
<div style="height: 300px; width: 400px;" class='viewer_3Dmoljs' data-pdb='1YCR' 
     data-backgroundcolor='white' data-style='line' 
     data-select1='chain:A' data-surface1='opacity:0.8;colorscheme:whiteCarbon'
     data-select2='chain:B' data-style2='stick:colorscheme=Jmol'
     data-zoomto='chain:B'></div>
In [37]:
%%html

<div style="height: 300px; width: 400px; position: relative;" class='viewer_3Dmoljs' data-pdb='1YCR' 
     data-backgroundcolor='white' data-style='line' 
     data-select1='chain:A' data-surface1='opacity:0.8;colorscheme:whiteCarbon'
     data-select2='chain:B' data-style2='stick:colorscheme=Jmol'
     data-zoomto='chain:B'></div> 
        
<script>

$3Dmolpromise.then(function() {
$3Dmol.autoload();
});
$(".jp-InputArea .o:contains(html)").closest('.jp-InputArea').hide();
</script>

Usage: Viewer URL API¶

https://3dmol.org/viewer.html?pdb=1ycr&select=all&style=line& select=chain:B&style=stick:colorscheme~Jmol& select=chain:A&surface=colorscheme:whiteCarbon;opacity:0.8

Usage: py3Dmol¶

In [38]:
import py3Dmol
v = py3Dmol.view('pdb:1ycr', height=250, width="100%", style='line')
v.addSurface('VDW', { 'opacity': 0.8, 'colorscheme': 'whiteCarbon' },
             { 'chain': "A" }, { 'chain': "A" });
v.addStyle({ 'chain': "B" }, { 'stick': { 'colorscheme': 'Jmol' } });
v.zoomTo({ 'chain': "B" });
v.show()

3Dmol.js failed to load for some reason. Please check your browser console for error messages.

Bring the visualization close to the data... and the data scientist¶

Data Sources¶

Supports PDB and PubChem ids for automatic fetching of molecular data.

In [39]:
py3Dmol.view('cid:344',height=350,width="100%",style='stick').show()

3Dmol.js failed to load for some reason. Please check your browser console for error messages.

File Formats¶

pdb, sdf, mol2, xyz, cif, cdjson, mmtf, prmtop, gro, pqr, cube, and vasp

In [40]:
sdf = open('docked.sdf').read()
v = py3Dmol.view(height=350,width="100%")
v.addModels(sdf)
v.setStyle({'stick':{'colorscheme':'greenCarbon'}})
v.zoomTo().show()

3Dmol.js failed to load for some reason. Please check your browser console for error messages.

Animating Multi-Model Files¶

In [41]:
v = py3Dmol.view(height=350,width="100%")
v.addModelsAsFrames(sdf)
v.setStyle({'stick':{'colorscheme':'greenCarbon'}})
v.zoomTo()
v.animate({'interval':1000}).show()

3Dmol.js failed to load for some reason. Please check your browser console for error messages.

Symmetries¶

In [42]:
py3Dmol.view('pdb:4udv',style={'cartoon':{'color':'spectrum'}},width="100%").show() #TMV

3Dmol.js failed to load for some reason. Please check your browser console for error messages.

Symmetries¶

In [43]:
v = py3Dmol.view('pdb:4udv',options={'doAssembly':True},style={'cartoon':{'color':'spectrum'}},width="100%")
v.addSurface({},{'color':'white','opacity':0.8}).show()

3Dmol.js failed to load for some reason. Please check your browser console for error messages.

Symmetries¶

Crystallographers like to see how assymetric unit replicates in unit cell.

In [44]:
cif = open('cifex.cif').read()
v = py3Dmol.view(width='100%',height=350,viewergrid=(1,2))
v.addModel(cif,viewer=(0,0)); 
v.addModel(cif,'cif',{'doAssembly': True, 'wrapAtoms':True, 'duplicateAssemblyAtoms': True},viewer=(0,1))
v.setStyle('stick')
v.addUnitCell()
v.zoomTo().show()

3Dmol.js failed to load for some reason. Please check your browser console for error messages.

Selections¶

Specify what to style or create surface for. JavaScript object that is matched to individual atoms.

AtomSelection {
  resn: string; // residue name 
  elem: string; // element 
  hetflag: boolean; //heteroatom
  chain: string; //chain
  resi: number; //residue number, can be range ("5-10") or list ([5,10,32])
  atom: string; // atom name (e.g. CA) 
  ss: string; //secondary structure
  model: number; // model index
  frame: number; // frame index
  bonds: number; //number of bonds

  byres: boolean; // expand selection to include full residues
  expand: number;   // expand selection to include atoms within given distance 
  within: {sel: AtomSelection, distance: number}; // intersects selection with atoms within distance from sel 

  and: AtomSelection[]; //intersection of provide list of selections
  or: AtomSelection[]; //union of provided list of selections 
  not: AtomSelection;  //inverse of provided selection

  predicate: function; //custom predicate function
}

Selections¶

In [45]:
v = py3Dmol.view('pdb:3erk',style='cartoon',width='100%',height=400)
v.addStyle({'within':{'sel':{'resn':'SB4'},'distance':5}},{'sphere':{'radius':0.25}})
v.addStyle({'byres':True, 'within':{'sel':{'resn':'SB4'},'distance':5}},{'stick':{'radius':0.15}})
v.setStyle({'resn':'SB4'},{'stick':{'colorscheme':'chartreuseCarbon'}})
v.setStyle({'bonds':0},{'sphere':{'radius':0.35}})
v.zoomTo({'resn':'SB4'}).show()

3Dmol.js failed to load for some reason. Please check your browser console for error messages.

Styles¶

Styles are applied per-atom. Specified as JavaScript object.

AtomStyleSpec {
  line: LineStyleSpec; //bonds as lines
  stick: StickStyleSpec; //bonds as sticks (cylinders)

  cross: CrossStyleSpec; //atoms as crosses
  sphere: SphereStyleSpec; //atoms as spheres

  cartoon: CartoonStyleSpec; // secondary structure as cartoon
}

Sphere¶

SphereStyleSpec {    
    hidden: boolean; // don't show spheres

    radius: number; //fixed radius of sphere
    scale: number; //scale VDW radius by this amount

    colorscheme: ColorschemeSpec; // colorscheme
    color: ColorSpec; //color
    colorfunc: function; //arbitrary function to specify color
    opacity: number; //opacity
}
In [46]:
py3Dmol.view('cid:2519',style={'sphere':{'scale':0.75, 'colorscheme':'Jmol'}},width="100%").show()

3Dmol.js failed to load for some reason. Please check your browser console for error messages.

ColorSchemes¶

ColorschemeSpec = {
  prop: string; //poperty for gradient/map calculation    

  gradient: GradientType|string; //gradient specification for continuous properties
  min: number; //min val for gradient
  max: number; //max val for gradient
  mid: number; //mid val for gradient
  colors: Array<ColorSpec>; //colors for gradient

  map: Record<string, unknown>; //map specification for discrete properties

};
In [47]:
v = py3Dmol.view(width="100%")
v.addModel(open('1fas.pqr').read(),'pqr')
v.setStyle({'sphere': {'colorscheme': { 'prop': 'partialCharge',
    'gradient': 'rwb','min': -0.75, 'max': 0.75}}})
v.zoomTo().show()

3Dmol.js failed to load for some reason. Please check your browser console for error messages.

In [48]:
v = py3Dmol.view(data=open('af.pdb').read(),width="100%")
v.setStyle({'cartoon':{'colorscheme':{
    'prop': 'b', 'gradient':'linear', 'min': 70, 'max': 100, 
    'colors': ["blue","yellow","green"]}}}).show()

3Dmol.js failed to load for some reason. Please check your browser console for error messages.

Stick¶

StickStyleSpec {   
    hidden: boolean; //do not show sticks 
    radius: number; //fixed radius

    doubleBondScaling?: number; //radius scale for double bonds
    tripleBondScaling: number; //radius scale for triple bonds  
    dashedBondConfig: DashedBondSpec; //dashed bond properties
    dashedBonds: boolean; //draw all bonds as dashed    
    singleBonds: boolean; // draw all bonds as single bonds

    colorscheme: ColorschemeSpec; //colorscheme, overrides color
    color: ColorSpec; //fixed color
    colorfunc?: Function;   //arbitrary function to specify color     
    opacity: number; //opacity

    showNonBonded: boolean; //display nonbonded atoms as spheres 
}
In [49]:
py3Dmol.view("cid:10321", style={'stick':{ 'color': 'lightblue',
    'doubleBondScaling': 1, 'tripleBondScaling': 0.5, 'radius': 0.1}},width="100%").show()

3Dmol.js failed to load for some reason. Please check your browser console for error messages.

Cartoon¶

CartoonStyleSpec {
    hidden: boolean; //do not show

    colorscheme: ColorschemeSpec; //colorscheme
    color: ColorSpec; //color, 'spectrum' is shortcut for rainbow
    colorfunc: function; //custom coloring
    opacity: number    

    style: string; //trace, oval, rectangle (default), parabola, edged

    ribbon: boolean; //use constant strand width regradless of secondary structure
    thickness: number; //stand thickness
    width: number; //strand width

    arrows: boolean; //add arrows to beta sheets   
    tubes: boolean; //helices as cylinders   
}
In [50]:
v = py3Dmol.view(query='pdb:1dc9',width='100%',linked=True,viewergrid=(2,3))
v.setStyle({'cartoon':{'style':'trace'}},viewer=(0,0))
v.setStyle({'cartoon':{'arrows':True, 'tubes':True, 'style':'oval', 'color':'white'}},viewer=(0,1))
v.setStyle({'cartoon':{'style':'parabola','colorscheme':{'prop':'b','gradient':'sinebow','min':10,'max':25}}},viewer=(0,2))
v.setStyle({'cartoon':{'style':'edged','colorscheme':'greenCarbon'}},viewer=(1,0))
v.setStyle({'cartoon':{'style':'rectangle','color':'spectrum'}},viewer=(1,1))
v.setStyle({'cartoon':{'ribbon':True,'color':'lightblue','thickness':0.5}},viewer=(1,2)); v.zoomTo().show()

3Dmol.js failed to load for some reason. Please check your browser console for error messages.

Can handle nucleic acids...

In [51]:
v = py3Dmol.view('4c64',style='cartoon',width="100%")
v.rotate(90).show()

3Dmol.js failed to load for some reason. Please check your browser console for error messages.

Surfaces¶

From Introduction to Proteins: Structure, Function, and Motion. Amit Kessel & Nir Ben-Tal

Surfaces¶

SurfaceStyleSpec {
    colorscheme: ColorschemeSpec;    
    color: ColorSpec;
    opacity: number; //opacity

    voldata: VolumeData; //volumetric data for vertex color
    volscheme: Gradient; //gradient to map volumetric data to color
    volformat: string; //volume format
}

Surfaces¶

In [52]:
v = py3Dmol.view('4c64',width='100%',viewergrid=(1,3))
v.addSurface('VDW',viewer=(0,0)); v.addSurface('MS',viewer=(0,1)); v.addSurface('SAS',viewer=(0,2)); v.show()

3Dmol.js failed to load for some reason. Please check your browser console for error messages.

In [53]:
v = py3Dmol.view('4c64',width='100%',style='cartoon')
v.setStyle({'bonds':0},{'sphere':{'radius':0.5}})
v.addSurface('VDW',{'color':'white','opacity':0.8},{'hetflag':False}).show()

3Dmol.js failed to load for some reason. Please check your browser console for error messages.

In [54]:
v = py3Dmol.view('pdb:3erk',style={'cartoon':{},'stick':{'radius':0.1}},width='100%',height=400)
v.addSurface('MS',{'colorscheme':'whiteCarbon'},
                {'byres':True, 'hetflag':False, 'within':{'distance':5,'sel':{'resn':'SB4'}}})
v.setStyle({'resn':'SB4'},{'stick':{'colorscheme':'chartreuseCarbon'}})
v.rotate(90,'x'); v.zoomTo({'resn':'SB4'}).show()

3Dmol.js failed to load for some reason. Please check your browser console for error messages.

In [55]:
v = py3Dmol.view('pdb:3erk',style={'cartoon':{},'stick':{'radius':0.1}},width='100%',height=400)
v.addSurface('MS',{'colorscheme':'whiteCarbon'},
                {'byres':True, 'hetflag':False, 'within':{'distance':5,'sel':{'resn':'SB4'}}},
                {'hetflag':False})
v.setStyle({'resn':'SB4'},{'stick':{'colorscheme':'chartreuseCarbon'}})
v.rotate(90,'x'); v.zoomTo({'resn':'SB4'}).show()

3Dmol.js failed to load for some reason. Please check your browser console for error messages.

Surfaces¶

Can color based on values in volumetric data.

In [56]:
import base64
v = py3Dmol.view(data=open('4csv.pdb').read(),style='cartoon',viewergrid=(1,2),width='100%',height=380)
v.addSurface("MS", { 'voldata': base64.b64encode(open('4csv.ccp4.gz','rb').read()).decode(), 
        'volformat': 'ccp4.gz', 'volscheme': {'gradient':'rwb', 'min':-.25, 'max':.25}},viewer=(0,0))
v.addSurface("SAS", {'opacity':0.9, 'voldata': base64.b64encode(open('4csv.ccp4.gz','rb').read()).decode(), 
        'volformat': 'ccp4.gz', 'volscheme': {'gradient':'rwb', 'min':-.25, 'max':.25}},viewer=(0,1)).show()

3Dmol.js failed to load for some reason. Please check your browser console for error messages.

Isosurfaces from volumetric data¶

In [57]:
v = py3Dmol.view(data=open('1lo6.pdb').read(),style={'cartoon':{},'stick':{}},height=390,width='100%')
density = base64.b64encode(open('1lo6_2FOFC.ccp4','rb').read()).decode()
v.addVolumetricData(density,'ccp4',{'isoval': 0.3,'color': "blue",'wireframe': True, 
                                    'selection': {}, 'seldist': 3}).show()

3Dmol.js failed to load for some reason. Please check your browser console for error messages.

Isosurfaces from volumetric data¶

In [58]:
density = open('Dt.cube').read(); esp = open('ESP.cube').read()
v = py3Dmol.view(data=density,format='cube',style='stick',height=380,width='100%')
v.addVolumetricData(density, "cube", {'isoval': 0.005, 'smoothness': 2, 'opacity':.9, 
        'voldata': esp, 'volformat': 'cube', 
        'volscheme': {'gradient':'rwb', 'min':-.1, 'max':.1}});
v.zoom(2).show()

3Dmol.js failed to load for some reason. Please check your browser console for error messages.

Volumetric Rendering¶

In [59]:
data = open('benzene-homo.cube').read()
v = py3Dmol.view(data=data,format='cube',style='stick',height=380,width='100%')
v.addVolumetricData(data, 'cube', {
            'transferfn': [{ 'color': "blue", 'opacity': .075, 'value': 0.1 },
            { 'color': "blue", 'opacity': .001, 'value': 0.01 },
            { 'color': "white", 'opacity': 0, 'value': 0 },
            { 'color': "red", 'opacity': .001, 'value': -0.01 },
            { 'color': "red", 'opacity': .075, 'value': -0.1 }]}).show()

3Dmol.js failed to load for some reason. Please check your browser console for error messages.

Use Example: Pharmit¶

https://pharmit.csb.pitt.edu/search.html?SESSION=examples/4pps.json

Use Example: ColabFold¶

https://colab.research.google.com/drive/1aO_cJ8qK4EmgYPYpwDeX33cYMrHywy7d?usp=sharing

Use Example: Pedagogical Active Learning¶

In [60]:
%%html
<div id="alearn" style="width: 500px"></div>
<script>

    var divid = '#alearn';
	jQuery(divid).asker({
	    id: divid,
	    question: "Have you used an active learning environment in a classroom?",
		answers: ["No","Yes"],
        server: "https://bits.csb.pitt.edu/asker.js/example/asker.cgi",
		charter: chartmaker})
    
$(".jp-InputArea .o:contains(html)").closest('.jp-InputArea').hide();

</script>

OChem Recitation¶

Demo¶

http://3dmol.org/v?cid=2519&select=all&style=stick¶

Thank You!

In [61]:
%%html

<div style="height: 400px; width: 100%; z-index: -1;" class='viewerbackground' id='endpage' ></div>       

<script>
$3Dmolpromise.then(function() {
var viewer = $3Dmol.createViewer('endpage');
$3Dmol.get("https://files.rcsb.org/view/4udv.pdb").then(function(data) {
    
var model = null; //no symms
var model1 = null; //green
var model2 = null; //blue

model = viewer.addModel(data, "pdb");
model1 = viewer.addModel(data, "pdb", {doAssembly:true});
model2 = viewer.addModel(data, "pdb", {doAssembly:true});

var sym = model1.getSymmetries();
var i;
for (i = 0; i < sym.length; i++) {
    sym.splice(i, 1);
}
model1.setSymmetries(sym);


var sym2 = model2.getSymmetries();
for (i = 1; i < sym2.length; i++) {
    sym2.splice(i,1);
}
//sym2.splice(0, 1); //take out id
model2.setSymmetries(sym2);

viewer.addSurface($3Dmol.SurfaceType.VDW, {color: '0x003594', opacity:1}, {model: model1});
viewer.addSurface($3Dmol.SurfaceType.VDW, {color: '0xffb81c', opacity:1}, {model: model2});

viewer.zoomTo();
viewer.spin('z',0.25);   

viewer.render();
  
});
});
             
$(".jp-InputArea .o:contains(html)").closest('.jp-InputArea').hide();
</script>